package com.encapi.framework.handler.impl;


import com.encapi.framework.constant.EncapiConstant;
import com.encapi.framework.exception.DecryptBodyException;
import com.encapi.framework.exception.EncryptBodyException;
import com.encapi.framework.exception.ExceptionUtil;
import com.encapi.framework.handler.CryptHandler;
import com.encapi.framework.properties.RsaProperties;
import com.encapi.framework.util.RsaUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;

public class RsaCryptHandler implements CryptHandler {

    @Resource
    private RsaProperties rsaProp;

    @Override
    public String getAlgorithm() {
        return EncapiConstant.ALG_RSA;
    }

    @Override
    public String encrypt(String plainText, HttpServletRequest request, HttpHeaders headers) throws EncryptBodyException {
        try {
            return RsaUtil.privateEncrypt(plainText, this.getPrivateKey());
        } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException
                | UnsupportedEncodingException | BadPaddingException | IllegalBlockSizeException
                | InvalidKeySpecException e) {
            throw ExceptionUtil.buildEncryptEx(
                    "an error has occurred when plain text encrypted with aes algorithm cause by : %s", e.getMessage());
        }
    }

    @Override
    public String decrypt(String cipherText, HttpServletRequest request, HttpHeaders headers) throws DecryptBodyException {
        try {
            return RsaUtil.publicDecrypt(cipherText, this.getPublicKey());
        } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException
                | UnsupportedEncodingException | BadPaddingException | IllegalBlockSizeException
                | InvalidKeySpecException e) {
            throw ExceptionUtil.buildDecryptEx(
                    "an error has occurred when cipher text decrypted with aes algorithm cause by : %s", e.getMessage());
        }
    }

    /**
     * 获取令牌公钥
     * @return
     */
    private PublicKey getPublicKey() throws InvalidKeySpecException, NoSuchAlgorithmException {
        return RsaUtil.string2PublicKey(rsaProp.getPublicKey());
    }

    /**
     * 获取令牌私钥
     * @return
     */
    private PrivateKey getPrivateKey() throws InvalidKeySpecException, NoSuchAlgorithmException {
        return RsaUtil.string2PrivateKey(rsaProp.getPrivateKey());
    }
}
